
// ===============================================================================================================
// -*- C++ -*-
//
// Weapon.cpp - Weapon base class and weapons related interfaces.
//
// Copyright (c) 2011 Guilherme R. Lampert
// guilherme.ronaldo.lampert@gmail.com
//
// This code is licenced under the MIT license.
//
// This software is provided "as is" without express or implied
// warranties. You may freely copy and compile this source into
// applications you distribute provided that the copyright text
// above is included in the resulting source code.
//
// ===============================================================================================================

#include <Weapon.hpp>
#include <Renderer.hpp>

// =========================================================
// DoublebarrelShotgun Class Implementation
// =========================================================

DoublebarrelShotgun::DoublebarrelShotgun(int shells) : Weapon(), animName("Idle")
{
	name = "Doublebarrel Shotgun";

	if (shells)
	{
		numClips = (shells / 2); // Two shells per clip.

		if (shells >= 2)
		{
			bulletsInClip = 2;
			--numClips;
		}
	}

	const char errAnimLoad[] = "Failed to load a Doublebarrel Shotgun anim !";
	const char errSndLoad[] = "Failed to load a Doublebarrel Shotgun sound !";

	// Load the model and animations:

	DoomMD5AnimPtr anim;
	model = DoomMD5Factory::CreateModelFromFile("Assets/Models/Weapons/Doublebarrel/Doublebarrel.md5mesh");

	if (!model)
	{
		throw std::runtime_error("Failed to load the Doublebarrel Shotgun model.");
	}

	anim = DoomMD5Factory::CreateAnimFromFile("Assets/Models/Weapons/Doublebarrel/Idle.md5anim");

	if (!anim)
	{
		throw std::runtime_error(errAnimLoad);
	}

	model->RegisterAnimation(anim.Get(), "Idle");

	anim = DoomMD5Factory::CreateAnimFromFile("Assets/Models/Weapons/Doublebarrel/Reload.md5anim");

	if (!anim)
	{
		throw std::runtime_error(errAnimLoad);
	}

	model->RegisterAnimation(anim.Get(), "Reload");

	anim = DoomMD5Factory::CreateAnimFromFile("Assets/Models/Weapons/Doublebarrel/Fire.md5anim");

	if (!anim)
	{
		throw std::runtime_error(errAnimLoad);
	}

	model->RegisterAnimation(anim.Get(), "Fire");

	// Now, load the shotgun textures:

	int n = model->GetNumMeshes();

	while (n--)
	{
		DoomMD5Mesh * mesh = model->GetMesh(n);

		if (mesh->shader[0] != '\0')
		{
			std::string textureFile(mesh->shader);
			textureFile.append(".tga"); // FIXME: Currently there is only support for TGA images.
			mesh->textureObject = Renderer::Instance()->Create2DTextureFromFile(textureFile);
		}
	}

	// And finaly the sounds:

	sndFire = FMOD::SoundSystem::CreateSoundFromFile("Assets/Sounds/Weapons/Doublebarrel/Fire.wav");

	if (!sndFire)
	{
		throw std::runtime_error(errSndLoad);
	}

	sndEmpty = FMOD::SoundSystem::CreateSoundFromFile("Assets/Sounds/Weapons/Doublebarrel/Empty.wav");

	if (!sndEmpty)
	{
		throw std::runtime_error(errSndLoad);
	}

	sndReload = FMOD::SoundSystem::CreateSoundFromFile("Assets/Sounds/Weapons/Doublebarrel/Reload.wav");

	if (!sndReload)
	{
		throw std::runtime_error(errSndLoad);
	}
}

void DoublebarrelShotgun::Fire(void)
{
	if (bulletsInClip == 2)
	{
		sndFire->Play();
		animName = "Fire";
		bulletsInClip = 0;
	}
	else
	{
		Reload();
	}
}

void DoublebarrelShotgun::Reload(void)
{
	if (numClips > 0)
	{
		sndReload->Play();
		animName = "Reload";
		bulletsInClip = 2;
		--numClips;
	}
	else
	{
		sndEmpty->Play();
		animName = "Idle";
	}
}

void DoublebarrelShotgun::AddAmmoClip(void)
{
	++numClips;
}

void DoublebarrelShotgun::AddAmmo(int ammo)
{
	if (ammo)
	{
		numClips += (ammo / 2); // Two shells per clip.
	}
}

int DoublebarrelShotgun::TotalAmmo(void) const
{
	return (numClips * 2); // Two shells per clip.
}

void DoublebarrelShotgun::Update(float elapsedTime)
{
	DoomMD5AnimPtr anim = model->GetAnimation(animName);
	int loopComplete = model->Animate(anim.Get(), elapsedTime);

	if (loopComplete)
	{
		if (animName == "Fire")
		{
			Reload();
		}
		else if (animName == "Reload")
		{
			animName = "Idle";
		}

		model->Animate(anim.Get(), elapsedTime + 1); // Workaround for a smooth animation...
	}
}

bool DoublebarrelShotgun::HasFired(void) const
{
	return (animName.compare("Fire") == 0);
}